﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Assist;
using Autodesk.Revit.DB;
using YJKRevitKernel.ElementSearchUtility.LinkDocumentSuite;
using YJKRevitDimensionText.VerticalAutoDim.GeoModel;

namespace YJKRevitDimensionText.VerticalAutoDim.GeoTopIntersect
{
	internal sealed class GeoTopIntersectManager
	{
		public GeoTopIntersectManager(Autodesk.Revit.DB.Document doc, Plane pl, Transform transform)
		{
			this.Doc = doc;
			this.Plane = pl;
			this.Transform = transform;
		}

		public IList<IPlanarGeo> CreateGeoTopIntersect(List<Element> lstElemTarget)
		{
			List<IPlanarGeo> list = new List<IPlanarGeo>();
			foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
			{
				if (typeof(IGeoTopIntersectCreator).IsAssignableFrom(type) && !type.IsInterface)
				{
					IGeoTopIntersectCreator geoTopIntersectCreator = Activator.CreateInstance(type) as IGeoTopIntersectCreator;
					ElementFilter filter = geoTopIntersectCreator.Filter;
					foreach (Element element in lstElemTarget)
					{
						BoundingBoxXYZ boundingBoxXYZ = element.get_BoundingBox(null);
						LogicalAndFilter logicalAndFilter = new LogicalAndFilter(new BoundingBoxIntersectsFilter(new Outline(boundingBoxXYZ.Min, boundingBoxXYZ.Max + XYZ.BasisZ * AssistFunc.mmToFeet(1.0))), filter);
						List<BaseLinkDocumentResultBean> list2 = new FilteredElementCollectorLinkDocument(this.Doc).WherePass(logicalAndFilter).WhereElementIsNotElementType().ToBeans();
						if (geoTopIntersectCreator.IsElementValid != null)
						{
							list2 = list2.Where(geoTopIntersectCreator.IsElementValid).ToList<BaseLinkDocumentResultBean>();
						}
						foreach (BaseLinkDocumentResultBean baseLinkDocumentResultBean in list2)
						{
							Element useElement = baseLinkDocumentResultBean.UseElement;
							if (geoTopIntersectCreator.IsElementValidByGeo(element, useElement))
							{
								IPlanarGeo planarGeo = geoTopIntersectCreator.CreatePlanarGeo(useElement, this.Plane, this.Transform);
								planarGeo.Init();
								list.Add(planarGeo);
							}
						}
					}
				}
			}
			return list;
		}

		private readonly Document Doc;

		private readonly Plane Plane;

		private readonly Transform Transform;
	}
}
